<?php
/**
 * @property Core_Model_DbTable_Products $_productTable
 */
class Core_Model_Store extends YouNet_Db_Table_Row
{
	/**
	 * @var Core_Model_DbTable_Products
	 */
	private $_productTable = null;

	/**
	 * @var Core_Model_DbTable_Category_Customs
	 */
	private $_customCategoryTable	= null;
	
	/**
	 *
	 * @var Core_Model_DbTable_Category_Systems
	 */
	private $_systemCategoryTable = null;

	/**
	 *
	 * @var Core_Model_DbTable_Product_Images
	 */
	private $_productImageTable		= null;

	/**
	 *
	 * @var Core_Model_DbTable_Users 
	 */
	private $_userTable				= null;
	
	/**
	 *
	 * @var Zend_Db_Table_Rowset
	 */
	private $_listTopCategories		= null;

	/**
	 *
	 * @var array()
	 */
	private $_errorMessage = array();

	public function init()
	{
		parent::init();
		$this->_productTable		= Core_Model_DbTable_Products::getInstance();
		$this->_productImageTable	= new Core_Model_DbTable_Product_Images();
		$this->_userTable			= new Core_Model_DbTable_Users();
		$this->_systemCategoryTable	= Core_Model_DbTable_Category_Systems::getInstance();
		$this->_customCategoryTable = Core_Model_DbTable_Category_Customs::getInstance();
	}

	public function getErrorMessage()
	{
		return $this->_errorMessage;
	}

	public function getName()
	{
		return $this->name;
	}

	public function getBannerImageUrl()
	{
		if (!empty($this->banner_image))
		{
			return STATIC_URL . '/upload/store/' . $this->banner_image;
		}
		return STATIC_URL . '/upload/store/' . DEFAULT_BANNER_IMAGE;
	}

	public function getBannerThumbImageUrl()
	{
		if (!empty($this->banner_image))
		{
			return STATIC_URL . '/upload/store/thumbnail/' . $this->banner_image;
		}
		return STATIC_URL . '/upload/store/thumbnail/' . DEFAULT_BANNER_IMAGE;
	}

	public function getPageName()
	{
		if(isset($this->page_name))
		{
			return $this->page_name;
		}
		return 'Page';
	}
	
	public function getDescription()
	{
		return $this->description;
	}
	
	public function getDefaultLayout()
	{
		return $this->default_layout;
	}

	public function setErrorMessage(array $errorMessage)
	{
		$this->_errorMessage = $errorMessage;
	}

	public function getUnitCode()
	{
		return $this->unit_code;
	}

	public function getLocale()
	{
		return 'en_US';
	}
	/**
	 * Create a product from array info,
	 * the product is created after will be belong to this store
	 * @param array $arrData
	 * @param array $arrImages
	 * @return Core_Model_Product
	 */
	public function createProductFromParams(array $arrData, array $arrImages)
	{
		$product = $this->_productTable->createFromParams(
			$arrData + array('id_store' => $this->id)
		);
		/*@var $product Core_Model_Product*/
		if( $product->save() )
		{   
			if( $product->getCustomCategory() )
			{
				$product->getCustomCategory()->increaseTotalProductNumbers();
			}
			if( $product->getSystemCategory() )
			{
				$product->getSystemCategory()->increaseTotalProductNumbers();
			}
            if ($arrData['status'] == Core_Model_DbTable_Products::STATUS_SHOWN)
            {
				if( $product->getCustomCategory() )
				{
					$product->getCustomCategory()->increaseActiveProductNumbers();
				}
				if( $product->getSystemCategory() )
				{
					$product->getSystemCategory()->increaseActiveProductNumbers();
				}
            }            
            
			foreach($arrImages as $key => $value)
			{
				$this->_productImageTable->insert(
					array(
						'id_product'	=> $product->id,
						'description'	=> @current($arrData[$key]),
						'image'			=> $value
					)
				);
			}
			$this->increaseTotalProductNumbers();
			$this->_validateCacheCustomCategories();
		}
		return $product;
	}

	public function updateProductFromParams($id_product, array $arrData, array $arrImages)
	{
		$product =  $this->_productTable->fetchRow(array(
			'id = ?'		=> $id_product,
			'id_store = ?'	=> $this->id
		));
		/*@var $product Core_Model_Product*/
		$result = $product->updateFromParams($arrData);
		if( $result )
		{
			$arrIdProductImages			= $product->getArrIdProductImages();
			$arrIdUnusedProductImages	= array();
			$arrIdUsedProductImages		= array();

			foreach($arrImages as $key => $value)
			{
				$arrTemp	= explode('_',$key);
				$id_image	= $arrTemp[1];
				$arrIdUsedProductImages[] = $id_image;
				$productImageProduct = $this->_productImageTable->fetchRow(array(
					'id = ?'			=> $id_image,
					'id_product = ?'	=> $id_product
				));
				if( $productImageProduct )
				{
					if( $value )
					{
						$productImageProduct->image = $value;
					}
					$productImageProduct->description = @current($arrData[$key]);
					$productImageProduct->save();
				}
				else
				{
					$this->_productImageTable->insert(
						array(
							'id_product'	=> $product->id,
							'description'	=> @current($arrData[$key]),
							'image'			=> $value
						)
					);
				}
			}
			$arrIdUnusedProductImages = array_diff($arrIdProductImages, $arrIdUsedProductImages);
			if( count($arrIdUnusedProductImages) )
			{
				$where = $this->getTable()->getAdapter()->quoteInto('id IN (?)', $arrIdUnusedProductImages);
				$this->_productImageTable->delete($where);
			}
			$this->_validateCacheCustomCategories();
			$product->invalidateProductImagesCache();
		}
		return $product;
	}
	public function createStoreFromParams(array $params)
	{
		$id_system_category = end($params['id_system_category']);
		if( !$id_system_category )
		{
			$id_system_category = @prev($params['id_system_category']);
		}
		if( $id_system_category )
		{
			$params['id_system_category'] = $id_system_category;
		}
		
		$layouts = $params[Store_Form_Store::STORE_LAYOUT];
		$int_layout = 0;
		
		if(sizeof($layouts)>0)
		{
			$int_layout = array_sum($layouts);
		}
		
		$this->layout = $int_layout;
		$this->default_layout = $params[Store_Form_Store::DEFAULT_LAYOUT];
				
		$this->setFromArray($params);
		if ($params['action'] == 'create')
		{
			$this->time_created = time();
			$this->status		= Core_Model_DbTable_Stores::STATUS_HIDDEN;
		}
		$this->time_modified = time();
        
        if(!empty($params['shopping_cart_setting']))
        {
            $this->shopping_cart_setting = $params['shopping_cart_setting'][0];
        }
        else
        {
            $this->shopping_cart_setting = 0;
        }

		$this->save();
		
		return true;
	}

	/**
	 * Create a custom category from params
	 * The category is created after will be belong to this store
	 * @param array $params
	 * @return Core_Model_Category_Custom
	 */
	public function createCategoryFromParams(array $params, &$_err_essages = null)
	{
		$data = array();
		if( !$this->_preProcessCategoryName($params, $_err_essages) )
		{
			return false;
		}
		$data['name']			= isset($params['name'])?$params['name']:'';
		$data['description']	= isset($params['description'])?$params['description']:'';
		$data['id_store']		= $this->id;
		$data['id_user']		= $params['id_user'];

		if( !empty($params['id_parent']) )
		{
			$data['id_parent']		= $params['id_parent'];
		}

		$row = $this->_customCategoryTable->createRow($data);
		/*@var $row Core_Model_Category_Custom*/
		$row->z_order	= $this->_customCategoryTable->findNewZIndex($this->id, isset($data['id_parent'])?$data['id_parent']:NULL);
		if( $row->save() )
		{
			$path	= '';
			if( empty($row->id_parent) )
			{
				$path = $row->id.Core_Model_DbTable_Category_Customs::DELIMITER;				
			}
			else
			{
				$parentCategory = $row->getParentCategory();
				$path			= $parentCategory->path.$row->id.Core_Model_DbTable_Category_Customs::DELIMITER;
			}			
			$row->path		= $path;
			$row->save();
		}
		$this->_validateCacheCustomCategories();
		return $row;
	}
	
	private function _preProcessCategoryName(&$params,&$_err_essages = NULL)
	{
		if( isset($params['name']) )
		{
			$params['name'] = trim($params['name']);
		}
		if( empty($params['name']) )
		{
			return false;
		}
		$validator = new Zend_Validate_StringLength(array(
			'max'		=> 255,
			'encoding'	=> 'UTF-8'
		));
		if( !$validator->isValid($params['name']) )
		{
			if( is_array($_err_essages) )
			{
				$_err_essages[] = current($validator->getMessages());
			}
			return false;
		}
		return true;
	}

	public function updateCategoryFromParams(array $params, &$_err_essages = null)
	{
		if( !isset($params['id_category']) )
		{
			throw new Exception('Object is not found');
		}
		if( !$this->_preProcessCategoryName($params, $_err_essages) )
		{
			return false;
		}

		$data = array();
		$data['name']			= isset($params['name'])?$params['name']:'';
		if( !empty($params['id_parent']) )
		{
			$data['id_parent']		= $params['id_parent'];
		}
		$this->_validateCacheCustomCategories();
		$this->_customCategoryTable->updateByIdStore($data, $params['id_category'], $this->id);
		return true;
	}

	/**
	 *
	 * @param array $params
	 * @return boolean
	 * @throws Exception
	 */
	public function deleteCategoryFromParams(array $params)
	{
		if( !isset($params['id_category']) )
		{
			throw new Exception('Object is not found');
		}
		$id_category	= $params['id_category'];
		$category		= $this->_customCategoryTable->fineOneByIdStore($id_category, $this->id);
		if( empty($category) )
		{
			throw new Exception('Object is not found');
		}
		if( $category->canDelete() )
		{
			$this->_validateCacheCustomCategories();
			return $category->delete();
		}
		return false;
	}
	/**
	 *
	 * @param int $id_product
	 * @return Core_Mode_Product
	 */
	public function getProduct($id_product)
	{
		$productRow = $this->_productTable->findVisibleProduct($id_product);
		
		if(empty($productRow))
		{
			return null;
		}
		
		if ($productRow->id_store != $this->id)
		{
			throw new Exception('The product can not be accessed by this store');
		}
		$productRow->setStore($this);
		return $productRow;
	}

	public function doHide()
	{
		$this->status = Core_Model_DbTable_Stores::STATUS_HIDDEN;
		$this->save();
	}

	public function doShow()
	{
		if($this->canShow())
		{
			$this->status = Core_Model_DbTable_Stores::STATUS_SHOWN;
			$this->save();
		}
	}

	public function doDelete()
	{
		$this->status = Core_Model_DbTable_Stores::STATUS_DELETED;
		$this->save();
	}

	public function canShow()
	{
		$errPageName = array();
		$canShow = true;
		if (!empty($this->id))
		{
			$pagesRowSet = $this->getListPages();
			if (empty($pagesRowSet))
			{
				return false;
			}
			foreach ($pagesRowSet as $page)
			{
				/* @var $page Core_Model_Page*/
				if($page->hasShowStore())
				{
					$errPageName[] = $page->name;
					$canShow =  false;
				}
			}
		}
		$this->setErrorMessage($errPageName);
		return $canShow;
	}

	/**
	 *
	 * @param int $id_product
	 * @return Core_Model_Product
	 */
	public function findProductById($id_product, $isReadOnly = true)
	{
		$key = Core_Cache_IKeys::MODEL_PRODUCT . '_' . $this->id . '_' . $id_product;
		$data	= YouNet_Util::getObjectMemCache()->load($key);
		if( $data === false )
		{
			$product = $this->_productTable->getProductBelongToStore($this->id, $id_product);
			if( $product )
			{
				YouNet_Util::getObjectMemCache()->save($product->toArray(), $key);
			}
		}
		else
		{
			if( !$isReadOnly )
			{
				$config = array(
		            'table'    => $this->_productTable,
		            'data'     => $data,
		            'stored'   => true
		        );

		        $rowClass = $this->_productTable->getRowClass();
		        $product = new $rowClass($config);
		        $product->setFromArray($data);
	    	}
	    	else
	    	{
				$product = $this->_productTable->createRow($data);
				$product->setTable($this->_productTable);
			}
		}
		if( !empty($product) )
		{

			$product->setStore($this);
		}
		return $product;
	}

	public function getArrIdPages()
	{
		$arrReturn = array();
		$storePageRowSet = $this->getListPages();
		if ($storePageRowSet->count())
		{
			foreach ($storePageRowSet as $storePageRow)
			{
				$arrReturn[] = $storePageRow->id_page;
			}
		}
		return $arrReturn;
	}

	public function getListPages()
	{
		return $this->findDependentRowset('Core_Model_DbTable_Pages');
	}

	/**
	 *
	 * @param int $id_parent
	 * @return Zend_Db_Table_Rowset
	 */
	public function getListCategories($id_parent = NULL)
	{
		return $this->_customCategoryTable->getListByIdStore($this->id, $id_parent);
	}

	public function getArrCategories($id_parent = NULL)
	{
		$arrCategories	= array();
		$listCategories	= $this->getListCategories($id_parent);
		foreach($listCategories as $category)
		{
			/*@var $category Core_Model_Category*/
			$arrCategories[$category->id] = $category->getName();
		}
		return $arrCategories;

	}

	/**
	 * Get list CustomCategories
	 * @return Zend_Db_Table_Rowset
	 */
	public function getListTopCategories()
	{
		if( !$this->_listTopCategories )
		{
			$key	= Core_Cache_IKeys::TOP_CATEGORIES_BY_STORE.'_'.$this->id;
			$data	= YouNet_Util::getObjectMemCache()->load($key);
			if( $data === false )
			{
				$this->_listTopCategories = $this->_customCategoryTable->getListByIdStore($this->id, NULL);
				YouNet_Util::getObjectMemCache()->save($this->_listTopCategories->toArray(), $key);
			}
			else
			{
				$rawData  = array(
					'table'    => $this->_customCategoryTable,
					'data'     => $data,
					'readOnly' => true,
					'rowClass' => $this->_customCategoryTable->getRowClass(),
					'stored'   => true
				);
				$rowsetClass				= $this->_customCategoryTable->getRowsetClass();
				$this->_listTopCategories	= new $rowsetClass($rawData);
			}

		}
		return $this->_listTopCategories;
	}

	public function getArrTopCategories()
	{
		$arrTopCategories	= array();
		$listTopCategories	= $this->getListTopCategories();
		foreach($listTopCategories as $category)
		{
			/*@var $category Core_Model_Category*/
			$arrTopCategories[htmlspecialchars($category->path.'%')] = str_replace('&amp;', '&', $category->getName());
		}
		return $arrTopCategories;
	}

	public function getStatus()
	{
		switch ($this->status)
		{
			case Core_Model_DbTable_Stores::STATUS_SHOWN:
				return 'STATUS_SHOWN';
				break;
			case Core_Model_DbTable_Stores::STATUS_HIDDEN:
				return 'STATUS_HIDDEN';
				break;
			case Core_Model_DbTable_Stores::STATUS_DELETED:
				return 'STATUS_DELETED';
				break;
			default:
				return 'STATUS_UNDEFINED';
				break;
		}
	}
	
	public function isShown()
	{
		return $this->status == Core_Model_DbTable_Stores::STATUS_SHOWN;
	}

	public function getCategoryHierarchy($from_cache = true)
	{
		$refs = array();
		$list = array();

		$dataSet = $this->_customCategoryTable->getAllCategoriesByIdStore($this->id, $from_cache);
		/*@var $dataSet Zend_Db_Table_Rowset*/
		if( $dataSet->count() )
		{
			while($category = $dataSet->current())
			{
				/*@var $category Core_Model_Category*/
				$thisref = &$refs[ $category['id'] ];
				$thisref['id']				= $category['id'];
				$thisref['id_parent']		= $category['id_parent'];
				$thisref['name']			= $category->getName();
				$thisref['path']			= $category['path'];
				$thisref['number_active_products'] = $category['number_active_products'];
				if ($category['id_parent'] == 0) {
					$list[ $category['id'] ] = &$thisref;
				} else {
					$refs[ $category['id_parent'] ]['children'][ $category['id'] ] = &$thisref;
				}
				$dataSet->next();
			}
		}
		return $list;
	}

	public function findProductsBelongToStore($params, $pageNumber, $arrSort = array(), $item_per_page = 12)
	{
		$params['id_store'] = $this->id;
		$paginator = $this->_productTable->findProductsBelongToStore($params, $pageNumber, $arrSort, $item_per_page);
		if(count($paginator))
		{
			foreach($paginator as $row)
			{
				$row->setStore($this);
			}
		}
		return $paginator;
	}
	
	
	public function getCustomBreadscrumb($path)
	{
		$rowSet = $this->_customCategoryTable->getCategoryListByPath($path);
		$arrayCategories = array();

		foreach ($rowSet as $row)
		{
			$arrayCategories[htmlspecialchars($row->path . '%')] = $row->name;
		}
        
        $is_match = preg_match('/\-\%$/', $path);
        if($is_match == 0)
        {
            $arrayCategories[$path] = Core_Util::translate('Others');
        }
		
		return $arrayCategories;
	}

    public function showProduct($id_product)
    {
        $status = $this->_productTable->changeStatusByIdProduct(
            $id_product,
            $this->id,
            Core_Model_DbTable_Products::STATUS_SHOWN
        );

        if($status)
        {
            $product = $this->getProduct($id_product);
			if( $product->getCustomCategory() )
			{
				$product->getCustomCategory()->increaseActiveProductNumbers();
			}
			if( $product->getSystemCategory() )
			{
				$product->getSystemCategory()->increaseActiveProductNumbers();
			}
        }
		
		$this->_validateCacheCustomCategories();
		
        return $status;
    }

    public function hideProduct($id_product)
    {

        $status = $this->_productTable->changeStatusByIdProduct(
            $id_product,
            $this->id,
            Core_Model_DbTable_Products::STATUS_HIDDEN
        );

		if($status)
		{
			$product = $this->getProduct($id_product);            
			if( $product->getCustomCategory() )
			{
				$product->getCustomCategory()->decreaseActiveProductNumbers();
			}
			if( $product->getSystemCategory() )
			{
				$product->getSystemCategory()->decreaseActiveProductNumbers();
			}
		}
		
		$this->_validateCacheCustomCategories();
		
        return $status;
    }

	public function getNumberOfActiveProduct()
	{
		return $this->_customCategoryTable->getNumberOfActiveProduct($this->id);
	}

	public function getNumberOfAllProduct()
	{
		return $this->_customCategoryTable->getNumberOfTotalProduct($this->id);
	}

	public function getNumberOfInActiveProduct()
	{
		throw new Exception('Not implemented yet');
	}

    public function deleteProduct($id_product)
    {        
        $product = $this->_productTable->getProductBelongToStore($this->id, $id_product);
        $status = $this->_productTable->deleteByIdProduct(
            $id_product,
            $this->id
        );        
        //Decrease
        if ($status)
        {   
			if( $product->getCustomCategory() )
			{
				$product->getCustomCategory()->decreaseTotalProductNumbers();
				if ($product->status == Core_Model_DbTable_Products::STATUS_SHOWN)
				{
					$product->getCustomCategory()->decreaseActiveProductNumbers();
				}
			}
			$this->decreaseTotalProductNumbers();
        }
        $this->_validateCacheCustomCategories();
        return $status;
    }

	public function increaseTotalProductNumbers()
	{
		$this->products++;
		$this->save();
	}
	
	public function decreaseTotalProductNumbers()
	{
		$this->products--;
		$this->save();
	}
	
	public function hasSkuExist($sku)
	{
		$product = $this->_productTable->fetchRow(array(
			'sku = ?'		=> $sku,
			'id_store = ?'	=> $this->id
		));
		return $product != NULL;
	}

	protected function _doUpdate()
	{
		$this->validateCaching();
		parent::_doUpdate();
	}
	public function validateCaching()
	{
		$this->_validateCacheStorePages();
	}

	private function _validateCacheStorePages()
	{
		foreach($this->getArrIdPages() as $id_page)
		{
			$key = Core_Cache_IKeys::MODEL_STORE_BY_PAGE.'_'.$id_page;
			YouNet_Util::getObjectMemCache()->remove($key);
			Store_Paginator::invalidateCacheByIdPage($id_page);
		}
	}

	private function _validateCacheCustomCategories()
	{
		$arrPrefixs = array(Core_Cache_IKeys::ALL_CATEGORIES_BY_STORE, Core_Cache_IKeys::TOP_CATEGORIES_BY_STORE);
		foreach ($arrPrefixs as $prefix)
		{
			$key = $prefix . '_' . $this->id;
			YouNet_Util::getObjectMemCache()->remove($key);
		}
	}
	
	/**
	 *
	 * @return Core_Model_User
	 */
	public function getCreator()
	{
		return $this->_userTable->findOne($this->id_user);
	}
	
	public function getLanguage()
	{
		if( !empty($this->language) )
		{
			return $this->language;
		}
		return 'en_US';
	}
	
	/**
	 * @return Core_Model_Category_System
	 */
	public function getSystemCategory()
	{
		static $arrCategories = array();
		if( !isset($arrCategories[$this->id_system_category]) )
		{
			$arrCategories[$this->id_system_category] = $this->_systemCategoryTable->findOne($this->id_system_category);
		}
		return $arrCategories[$this->id_system_category];
	}
	public function getCssPath()
	{
		if (!empty($this->css))
			return UPLOAD_PATH . '/' . STORE_CSS_FOLDER . '/' . $this->css;
		return '';
	}
	public function getCssLink()
	{
		if (!empty($this->css))
			return UPLOAD_URL . '/' . STORE_CSS_FOLDER . '/' . $this->css;
		return '';
	}	
	public function moveCustomCategory($id_category, $id_category_parent = null, $id_above = null)
	{
		$result = $this->_customCategoryTable->moveCategoryByIdStore($id_category, $this->id, $id_category_parent, $id_above);
		$this->_validateCacheCustomCategories();
		$this->_productTable->validateAllProductsByIdStore($this->id);
	}
	
	public function getCookieLayoutKey()
	{
		return 'sl_'.$this->id.'_'.$this->time_modified;
	}
	
	public function getCookieSortKey()
	{
		return 'ss_' . $this->id;
	}
    
    public function getCookieRecentViewed()
    {
        return 'srv_' . $this->id;
    }
    
    public function getAllRecentViewedProducts($rv_products){
        $list_products = array();
        arsort($rv_products);
        foreach ($rv_products as $id_product => $time){
            $product = $this->findProductById($id_product);
            if($product->status == Core_Model_DbTable_Products::STATUS_SHOWN){
                $list_products[] = $product;
            }
        }
        return $list_products;
    }
    
    public function getCurrency(){
        $currency = DEFAULT_CURRENCY;
        if(!empty($this->unit_code)){
            $currency = $this->unit_code;
        }
        return $currency;
    }
    
    public function getNumberNewOrders(){
        if(!empty($this->id)){
            return Core_Model_DbTable_Carts::getInstance()->getNumberNewOrders($this->id);
        }
        return 0;
    }
}
